/**
 * 普贴打印小程序 CPCL打印 sdk
 * @author zyc
 * @date 2021/05/27
 */
import GBK from './lib/gbk.min';
class putyCpclUtils{
  writeData = "";
  /**
   * @typeof CPCL开始命令
   * @param {int} offset 整个标签的水平偏移量,单位毫米
   * @param {int} width 标签宽 单位毫米 最大48
   * @param {int} height 标签最大高度，单位毫米 最大60
   * @param {int} page 打印标签的数量，最大 1024 张
   */
  init(offset,width,height,page){
    if(!width || width > 100){width = 100}
    if(!height || height > 100){height = 100}
    let _offset = parseInt(offset * 8);
    let _height = parseInt(height * 8);
    let _width = parseInt(width * 8);
    this.writeData = `! ${_offset} 200 200 ${_height} ${page}\r\n`;
    this.writeData += `PAGE-WIDTH ${_width}\r\n`;
    return this;
  }
  /**
   * @typeof 打印文本
   * @param rotate 旋转角度 0、90、180、270
   * @param font      24    字符(12*24)，汉字(24*24)
   *                  55    字符(8*16)，汉字(16*16)
   * @param size      字符高度选择 ----> 0 1 2 3 4 5 6 7 纵向放大 size 纵向放大 1(正常) 2(2倍高) 3 4 5 6 7 8
   *                  字符宽度选择 ----> 0 10 20 30 40 50 60 70 横向放大 size  1(正常) 2(2倍高) 3 4 5 6 7 8
   *                  示列:当传入3时，纵向放大3倍
   *                  当传入30时，横向放大3倍
   *                  当传入33时，横纵向同时放大3倍
   * @param x         x坐标，单位毫米
   * @param y         y坐标，单位毫米
   * @param content   文本内容
   */
  text(rotate,font,size,x,y,content){
    let _x = parseInt(x * 8)
    let _y = parseInt(y * 8)
    if (!rotate) {
      this.writeData += `TEXT ${font} ${size} ${_x} ${_y} ${content}\r\n`;
    }else{
      this.writeData += `TEXT${rotate} ${font} ${size} ${_x} ${_y} ${content}\r\n`;
    }
    return this;
  }
  /**
   * @typeof 字体间距
   * @param n 字符与字符之间的间隔大小 n*0.125mm
   */
  spacing(n){
    this.writeData += `SETSP ${parseInt(n)}\r\n`
    return this;
  }
  /**
   * @typeof 字体加粗开始指令
   */
  textBoldStart(){
    this.writeData += `SETBOLD 1\r\n`
    return this;
  }
  /**
   * @typeof 字体加粗取消
   */
  textBoldEnd(){
    this.writeData += `SETBOLD 0\r\n`;
    return this;
  }

  /**
   * @typeof 设置文本对齐方式
   * @param align   0默认左对齐  1居中   2右对齐
   *                ①只对字符，条码有效，对线段BOX指令无效。
   *                ②当X坐标为0时，字符和条码沿坐标原点对称打印。
   */
  textAlign(align){
    switch (align) {
      case 1:
        this.writeData += `CENTER\r\n`;
        break;
      case 2:
          this.writeData += `RIGHT\r\n`;
          break;
      default:
        this.writeData += `LEFT\r\n`;
        break;
    }
    return this;
  }
  /**
   * @typeof 反白线段指令
   * @param xTop    左上角X坐标
   * @param yTop    左上角Y坐标
   * @param xBottom 水平线段的右上角或者垂直线段的左下角的X坐标
   * @param yBottom 水平线段的右上角或者垂直线段的左下角的Y坐标
   * @param width   反白线段的线宽
   */
  antiWhite(xTop, yTop, xBottom, yBottom, width){
    let _xTop = parseInt(xTop * 8)
    let _yTop = parseInt(yTop * 8)
    let _xBottom = parseInt(xBottom * 8)
    let _yBottom = parseInt(yBottom * 8)
    let _width = parseInt(width * 8)
    this.writeData += `INVERSE-LINE ${_xTop} ${_yTop} ${_xBottom} ${_yBottom} ${_width}`
    return this;
  }

  /**
   * @typeof 打印一维条码
   * @param direction true    打印横向条码
   *                  false   打印纵向条码
   * @param type     type 条码类型，一维条码的类型有:
   *                  Type值     条码类型
   *                  UPCA       UPC-A
   *                  UPCE       UPC-E
   *                  EAN13      JAN13 (EAN13)
   *                  EAN8       JAN 8 (EAN8)
   *                  39         CODE39
   *                  CODABAR    CODABAR
   *                  93         CODE93
   *                  128        CODE128(Auto)
   * @param width     条码宽度. 点为单位   宽度是根据内容及黑白条比例定
   * @param ratio     宽条宽和窄条宽比率
   *                  0 = 1.5:1   20 = 2.0:1
   *                  1 = 2.0:1   21 = 2.1:1
   *                  2 = 2.5:1   22 = 2.2:1
   *                  3 = 3.0:1   23 = 2.3:1
   *                  4 = 3.5:1   24 = 2.4:1
   *                  25 = 2.5:1
   *                  26 = 2.6:1
   *                  27 = 2.7:1
   *                  28 = 2.8:1
   *                  29 = 2.9:1
   *                  30 = 3.0:1
   * @param height    条码高度. 单位毫米
   * @param x         x坐标，单位毫米
   * @param y         y坐标，单位毫米
   * @param data      一维码内容
   */
  Barcode(direction,type,width,ratio,height,x,y,content){
    let _height = parseInt(height * 8);
    let _x = parseInt(x * 8);
    let _y = parseInt(y * 8);
    if(direction){
      this.writeData += `BARCODE ${type} ${width} ${ratio} ${_height} ${_x} ${_y} ${content}\r\n`
    }else{
      this.writeData += `VBARCODE ${type} ${width} ${ratio} ${_height} ${_x} ${_y} ${content}\r\n`
    }
    return this;
  }
  /**
   * 打印条码内容
   * @param font      24    字符(12*24)，汉字(24*24)
   *                  55    字符(8*16)，汉字(16*16)
   * @param size      字符高度选择 ----> 0 1 2 3 4 5 6 7 纵向放大 size 纵向放大 1(正常) 2(2倍高) 3 4 5 6 7 8
   *                  字符宽度选择 ----> 0 10 20 30 40 50 60 70 横向放大 size  1(正常) 2(2倍高) 3 4 5 6 7 8
   *                  示列:当传入3时，纵向放大3倍
   *                  当传入30时，横向放大3倍
   *                  当传入33时，横纵向同时放大3倍
   * @param offset    文字偏移 单位mm
   */
  BarcodeText(font,size,offset){
    this.writeData += `BARCODE-TEXT ${font} ${size} ${parseInt(offset * 8)}\r\n`
    return this;
  }
  /**
   * 打印条码文字结束
  */
  BarcodeTextEnd(){
    this.writeData += `BARCODE-TEXT OFF\r\n`
    return this;
  }
  /**
   * @typeof 二维码指令
   * @param direction true    打印横向条码
   *                  false   打印纵向条码
   * @param x         水平方向起始位置
   * @param y         垂直方向起始位置
   * @param Mn        QR 条码模式.n 范围：1 或者 2，默认：2
   * @param Un        放大倍数.n 范围：1 到 6，默认：6
   * @param rank      纠错等级
   *                  H-可靠性等级(Level H)
   *                  Q-高可靠性等级(Level Q)
  *                   M-标准等级(Level M)
   *                  L-高密度等级(Level L)
   * @param content      二维码数据
   */
  QrCode(direction,x,y,Mn,Un,rank,content){
    let _x = parseInt(x * 8);
    let _y = parseInt(y * 8);
    if(!Mn){Mn = 2}
    if(!Un){Un = 6}
    if(direction){
      this.writeData += `BARCODE QR ${_x} ${_y} M ${Mn} U ${Un}\r\n${rank}A,${content}\r\nENDQR\r\n`
    }else{
      this.writeData += `VBARCODE QR ${_x} ${_y} M ${Mn} U ${Un}\r\n${rank}A,${content}\r\nENDQR\r\n`
    }
    return this;
  }

  /**
   * @typeof 矩形框指令
   * @param xTop    左上角X坐标
   * @param yTop    左上角Y坐标
   * @param xBottom 右下角X坐标
   * @param yBottom 右下角Y坐标
   * @param width   形成矩形的线宽
   */
  rectangle(xTop,yTop,xBottom,yBottom,width){
    let _xTop = parseInt(xTop * 8)
    let _yTop = parseInt(yTop * 8)
    let _xBottom = parseInt(xBottom * 8)
    let _yBottom = parseInt(yBottom * 8)
    let _width = parseInt(width * 8)
    this.writeData += `BOX ${_xTop} ${_yTop} ${_xBottom} ${_yBottom} ${_width}\r\n`
    return this;
  }

  /**
   * @typeof 线段指令
   * @param xTop    左上角X坐标
   * @param yTop    左上角Y坐标
   * @param xBottom 右下角X坐标
   * @param yBottom 右下角Y坐标
   * @param width   形成线段的线宽
   */
  line(xTop,yTop,xBottom,yBottom,width){
    let _xTop = parseInt(xTop * 8)
    let _yTop = parseInt(yTop * 8)
    let _xBottom = parseInt(xBottom * 8)
    let _yBottom = parseInt(yBottom * 8)
    let _width = parseInt(width * 8)
    this.writeData += `LINE ${_xTop} ${_yTop} ${_xBottom} ${_yBottom} ${_width}\r\n`
    return this;
  }
  /**
   * @typeof 图片打印指令
   * @param imageData canvas rgb数据
   * @param width 宽度 单位px 需要是8的倍数
   * @param height  高度 单位px 需要是8的倍数
   */
  image(imageData,width,height){
    // let imageData = ctx.getImageData(0,0,width,height);
		let pixels = imageData;
		let binarys = "";
		for (let i=0; i<pixels.length; i+=4){
			const r = pixels[i];
			const g = pixels[i + 1];
			const b = pixels[i + 2];
			let gray = parseInt((r+g+b)/3)
      const binarye = gray >= 180 ? 255 : 0;
			if((r+g+b) >= 700){
				binarys+='0'
			}else if(pixels[i + 3] >= 120){
				binarys+='1'
			}else{
				binarys+='0'
			}
			pixels[i] = binarye;
      pixels[i + 1] = binarye;
      pixels[i + 2] = binarye;
		}
		// ctx.putImageData(imageData, 0,0)
		var hexLookup = {
      '0000': '0',
      '0001': '1',
      '0010': '2',
      '0011': '3',
      '0100': '4',
      '0101': '5',
      '0110': '6',
      '0111': '7',
      '1000': '8',
      '1001': '9',
      '1010': 'A',
      '1011': 'B',
      '1100': 'C',
      '1101': 'D',
      '1110': 'E',
      '1111': 'F'
		};
		var hex = '';
		let binary = binarys;
		var yu = binary.length % 4
    if (yu != 0) {
      for (var i = 0; i < 4-yu; i++) {
        binary+="0"
      }
		}
		for (var i = 0; i < binary.length; i += 4) {
      var current = binary[i] + binary[i + 1] + binary[i + 2] + binary[i + 3];
      hex = hex + hexLookup[current];
    }
    var _width = parseInt(width / 8);
    this.writeData += `EG ${_width} ${height} 0 0\r\n${hex}\r\nEND\r\n`;
    return this;
  }
  /**
   * @typeof 自动走到下一间隙，间隙纸必设
   */
  next(){
    this.writeData += "FORM\r\n"
    return this;
  }
  /**
   * @typeof 导出数据
   */
  put(){
    this.writeData += "PRINT\r\n";
    return GBK.encode(this.writeData);
  }
}

export default new putyCpclUtils();